Change StrawberryConfig to be a dictionary instead of a class#4039
Change StrawberryConfig to be a dictionary instead of a class#4039
Conversation
Reviewer's GuideTransition schema configuration to a dictionary-based API by introducing a TypedDict, deprecating the StrawberryConfig class, adding normalization logic, refactoring internal accesses, and updating documentation. File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Apollo Federation Subgraph Compatibility Results
Learn more: |
035c8a9 to
3823b9c
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4039 +/- ##
==========================================
- Coverage 94.39% 94.29% -0.10%
==========================================
Files 534 535 +1
Lines 34834 34878 +44
Branches 1831 1839 +8
==========================================
+ Hits 32881 32889 +8
- Misses 1657 1691 +34
- Partials 296 298 +2 🚀 New features to boost your workflow:
|
f22d944 to
a0a908b
Compare
CodSpeed Performance ReportMerging #4039 will not alter performanceComparing Summary
|
a0a908b to
aba9676
Compare
StrawberryConfig class| ) | ||
|
|
||
| if len(request_data) > self.schema.config.batching_config["max_operations"]: | ||
| if len(request_data) > self.schema.config["batching_config"]["max_operations"]: |
There was a problem hiding this comment.
I'm not sure about the visual noise we're adding here 😬
But I love that the config is now a dict for the user, so I guess we've got to live with it internally :D
| if TYPE_CHECKING: | ||
| # For type checkers, show these as instance attributes | ||
| auto_camel_case: bool | None | ||
| name_converter: NameConverter | ||
| default_resolver: Callable[[Any, str], object] | ||
| relay_max_results: int | ||
| relay_use_legacy_global_id: bool | ||
| disable_field_suggestions: bool | ||
| info_class: type[Info] | ||
| enable_experimental_incremental_execution: bool | ||
| _unsafe_disable_same_type_validation: bool | ||
| batching_config: BatchingConfig | None |
There was a problem hiding this comment.
on the other hand, how would we make clear the default values in an accessible way? For the dataclass they were immediately visiblei n the type overlay. looking into _complete_config seems more complicated and less direct
There was a problem hiding this comment.
I guess we need to make a custom language server? :P
but probably better docs?
There was a problem hiding this comment.
yea let's make sure everything is documented in here, maybe in a short table: https://strawberry.rocks/docs/types/schema-configurations#available-configurations
we could auto generate that from the code as well with minor adjustments :P
There was a problem hiding this comment.
Pull Request Overview
This PR migrates the schema configuration API from a class-based approach (StrawberryConfig dataclass) to a dictionary-based approach. The migration includes updating all internal usages from attribute access (config.field) to dictionary access (config["field"]), updating tests and documentation, and providing a codemod tool for user migration.
Key Changes
StrawberryConfigchanged from a dataclass to a dict subclass (StrawberryConfigDict) with backwards-compatible attribute access- All config access patterns updated to dictionary-style throughout the codebase
- Tests updated to use dictionary syntax for configuration
- Documentation and migration guide added
Reviewed Changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| strawberry/schema/config.py | Core config implementation changed from dataclass to TypedDict/dict-based system |
| strawberry/schema/schema.py | Updated to use _complete_config() function and dictionary access patterns |
| strawberry/schema/schema_converter.py | All config accesses changed to dictionary-style (config["key"]) |
| strawberry/schema/base.py | Type annotations and config access updated |
| strawberry/utils/locate_definition.py | Config access changed to dictionary-style |
| strawberry/types/arguments.py | Config access changed to dictionary-style |
| strawberry/relay/utils.py | Config access changed to dictionary-style |
| strawberry/printer/printer.py | Config access changed to dictionary-style |
| strawberry/http/base.py | Config access changed to dictionary-style with nested access |
| strawberry/federation/schema.py | Config access changed to dictionary-style |
| strawberry/extensions/directives.py | Config access changed to dictionary-style |
| strawberry/codemods/config_to_dict.py | New codemod tool for automated migration |
| strawberry/codemods/init.py | Export new codemod |
| tests/schema/test_config.py | Tests updated but still use class instantiation syntax |
| tests/schema/test_camel_casing.py | Tests updated to dictionary syntax |
| tests/test_printer/*.py | Tests updated to dictionary syntax |
| tests/federation/printer/*.py | Tests updated to dictionary syntax |
| tests/objects/generics/test_names.py | Refactored to use NameConverter directly instead of via config |
| docs/types/schema-configurations.md | Documentation updated with dictionary examples |
| docs/types/defer-and-stream.md | Documentation updated with dictionary examples |
| docs/guides/query-batching.md | Documentation updated with dictionary examples |
| docs/breaking-changes/0.285.0.md | New migration guide added |
| docs/breaking-changes.md | Added link to new migration guide |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class StrawberryConfigDict(dict[str, Any]): | ||
| """Configuration for Strawberry Schema. | ||
|
|
||
| This is a dictionary-like class that defines the configuration options for a | ||
| Strawberry schema. All fields are optional - missing fields will be filled with | ||
| sensible defaults. | ||
|
|
||
| This class supports both dictionary-style access (config["name_converter"]) and | ||
| attribute-style access (config.name_converter) for backwards compatibility. | ||
|
|
||
| Example: |
There was a problem hiding this comment.
StrawberryConfigDict is missing a custom __init__ method to handle initialization with keyword arguments. When users call StrawberryConfig(auto_camel_case=True) (as shown in test_config.py), the built-in dict __init__ creates {'auto_camel_case': True} without applying defaults or the auto_camel_case → name_converter conversion. This breaks backwards compatibility. Add an __init__ method that calls _complete_config to ensure proper initialization.
| # Backwards compatibility: StrawberryConfig is StrawberryConfigDict | ||
| # This works at runtime and for type checking because StrawberryConfigDict | ||
| # has TYPE_CHECKING annotations that make attributes visible to type checkers | ||
| StrawberryConfig = StrawberryConfigDict |
There was a problem hiding this comment.
The breaking changes documentation (docs/breaking-changes/0.285.0.md) states that using StrawberryConfig as a class will show a DeprecationWarning, but no such warning is emitted in the code. Either add a deprecation warning mechanism or update the documentation to reflect that the old syntax is simply not recommended rather than deprecated with a warning.
|
|
||
| # List of breaking changes and deprecations | ||
|
|
||
| - [Version 0.285.0 - Deprecate StrawberryConfig Class - 30 October 2025](./breaking-changes/0.285.0.md) |
There was a problem hiding this comment.
polish: this is not following the pattern of the ones below
I wanted to make it backwards compatibile, but not fully sure it is worth it, since the user changes should be pretty small